home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CP14.ARJ / CPFUNCTS.C < prev    next >
C/C++ Source or Header  |  1992-03-20  |  10KB  |  524 lines

  1. /*
  2. LISTING 3
  3. */
  4.  
  5. /* function module for the program 'cp'
  6.    the cp program must be compiled with the large model */
  7.  
  8. /***********************************************************
  9.  
  10.  cpfuncts.c - function module for the program 'cp'
  11.  
  12.  copyright 1987, Stewart A. Nutter
  13.  
  14.  written by: Stewart A. Nutter
  15.  
  16.  ***********************************************************/
  17.  
  18.  
  19. #define MAINMODULE 0
  20. #include "cp.h"        /* v1.1 */
  21.  
  22. /* v1.1 Global prototypes */
  23. int find_mod(char *buf);
  24. void getstats(void);
  25. int doprint(int n);
  26. void pagebreak(void);
  27. void leftmargin(void);        /* v1.4 */
  28. char getnext(FILE *stream);
  29. void pushc(char c);
  30. int strcheck(char c);
  31. int addlist(struct Func_list *p, char *buf, int cnt);
  32.  
  33. /* v1.1 local prototypes */
  34. static char getchars(FILE *stream);
  35. static void setpage(struct Mod_list *ptr);
  36. static void pblock(char *pre, char *fptr, char *mptr, char *sptr, int cnt);
  37. static int recur_chk(char *buf);
  38.  
  39.  
  40. /* getnext - get the next character from the stream */
  41.  
  42. char getnext(FILE *stream)
  43.  
  44. {
  45.     register char c;
  46.     static int qflag = 0, cflag = 0, eflag = 0;
  47.     static int dflag = 0, aflag = 0, ncnt = 0;
  48.     static int fp;
  49.     int b, done;
  50.  
  51.     done = 1;
  52.     do {
  53.         if ((qflag | cflag | eflag | dflag | aflag) == 0)
  54.             done = 1;
  55.         c = getchars(stream);
  56.  
  57. /* process escape sequence characters */
  58.  
  59.         if (eflag && c != 0x1a) {
  60.             if (c >= '0' && c <= '7' && ncnt < 3)
  61.                 ncnt++;
  62.             else {
  63.  
  64. /* had less than the 3 octal digits */
  65.  
  66.                 if (ncnt < 3 && ncnt > 0)
  67.                     pushc(c);
  68.                 ncnt = 0;
  69.                 eflag = 0;
  70.             }
  71.         } else if (cflag && c != 0x1a) {        /* skipping a comment */
  72.             if (firstcmt == 1) {
  73.                 if (c != '\n' && strlen(filecmt) < (width - 14)) {
  74.                     filecmt[fp] = c;
  75.                     fp++;
  76.                     filecmt[fp] = 0;
  77.                 } else {
  78.                     do {        /* remove extraneous spaces and tabs */
  79.                         b = getchars(stream);
  80.                     }
  81.                     while (b == ' ' || b == '\t');
  82.                     pushc(b);
  83.                     filecmt[fp++] = ' ';
  84.                     filecmt[fp] = '\0';
  85.                 }
  86.             }
  87.             if (c == '*') {
  88.                 b = getchars(stream);
  89.                 if (b == '/') {
  90.                     firstcmt = 2;                /* done with the comment */
  91.                     if (fp > 0)
  92.                         filecmt[fp - 1] = 0;    /* terminate the line */
  93.                     cflag = 0;
  94.                 } else
  95.                     pushc(b);
  96.             }
  97.         } else if (qflag && c != 0x1a) {        /* skipping a string */
  98.             if (c == 0x27)
  99.                 eflag = 1;
  100.             else if (c == '\"') {
  101.                 pushc(0x1b);
  102.                 qflag = 0;
  103.             }
  104.         } else if (dflag && c != 0x1a) {        /* defines/includes etc. */
  105.             if (c == '\n')
  106.                 dflag = 0;
  107.         } else if (aflag && c != 0x1a) {        /* skip a character */
  108.             if (c == 0x27) {
  109.                 aflag = 0;
  110.                 pushc(0x1b);
  111.             } else if (c == '\\')
  112.                 eflag = 1;
  113.         } else {
  114.             switch (c) {
  115.             case '\"':
  116.                 qflag = 1;
  117.                 break;
  118.             case 0x27:
  119.                 aflag = 1;
  120.                 break;
  121.             case '#':
  122.                 dflag = 1;
  123.                 break;
  124.             case '/':
  125.                 b = getchars(stream);
  126.                 if (b == '*') {
  127.  
  128.                     /* this is the first comment of the file */
  129.  
  130.                     if (firstcmt == 0) {
  131.                         firstcmt = 1;
  132.                         filecmt[0] = 0;
  133.                         fp = 0;
  134.                     }
  135.                     cflag = 1;
  136.                 } else {
  137.                     pushc(b);
  138.                 }
  139.                 break;
  140.             }
  141.         }
  142.         if (aflag || dflag || qflag || eflag || cflag)
  143.             done = 0;
  144.     }
  145.     while (!done && c != 0x1a);
  146.     if (c == 0x1a) {
  147.         ncnt = 0;
  148.         aflag = 0;
  149.         dflag = 0;
  150.         qflag = 0;
  151.         eflag = 0;
  152.         cflag = 0;
  153.     }
  154.     return (c);
  155. }
  156.  
  157.  
  158. /* getchars - read inputs from the file */
  159.  
  160. static char getchars(FILE *stream)
  161. {
  162.     register char c;
  163.  
  164.     if (pp != pc)
  165.         c = *--pp;
  166.     else {
  167.         c = fgetc(stream);
  168.         if (c == (char) EOF)        /* v1.1 */
  169.             c = 0x1a;
  170.         if (c == 0x0a) {
  171.             pMnames->length++;
  172.             pMnames->size++;        /* count the unseen <cr> */
  173.         }
  174.         pMnames->size++;
  175.     }
  176.     return (c);
  177. }
  178.  
  179. /* pushc - save the char. in a last in first out stack */
  180.  
  181. void pushc(char c)
  182. {
  183.     if ((pp - pc) < 1000)
  184.         *pp++ = c;
  185.     else {
  186.         fprintf(stderr, "\nProgram syntax error:");
  187.         fprintf(stderr, " Too many pushed characters.\n");
  188.         exit(1);
  189.     }
  190. }
  191.  
  192.  
  193. /* addlist - add the name to the list if different */
  194. /*           and if not one of the 'c' key words */
  195.  
  196. #define KEYS 5
  197.  
  198. int addlist(struct Func_list *p, char *buf, int cnt)
  199.  
  200. {
  201.     int i, ret;
  202.     static char *keywords[KEYS] =
  203.     {
  204.         "while",
  205.         "if",
  206.         "for",
  207.         "switch",
  208.         "return",
  209.     };
  210.  
  211.     for (i = 0; i < KEYS && strcmp(buf, keywords[i]) != 0; i++);
  212.  
  213.     if (i < KEYS)
  214.         return (0);
  215.  
  216.     for (i = 0; i < cnt && strcmp(buf, p->name); i++)
  217.         p++;
  218.  
  219.     if (i == cnt) {
  220.         ret = 1;
  221.         if ((pFlist->name = strdup(buf)) == NULL) {
  222.             fprintf(stderr, "Ran out of memory.\n");
  223.             exit(1);
  224.         }
  225.         pFlist->used = 1;
  226.         pFlist++;                /* point to the next empty cell */
  227.         Fqty++;
  228.         if (Fqty > MAXFNCTS) {
  229.             fprintf(stderr, "Too many functions.\n");
  230.             exit(1);
  231.         }
  232.     } else {
  233.         ret = 0;
  234.         p->used++;
  235.     }
  236.     return (ret);
  237. }
  238.  
  239.  
  240. /* find_mod - return the index of the linked list for
  241.               the indicated function. A -1 means that
  242.               the function name was not found in the list */
  243.  
  244. int find_mod(char *buf)
  245.  
  246. {
  247.     int lo, hi, mid;
  248.     int d;
  249.  
  250.     lo = 0;
  251.     hi = Mqty - 1;
  252.     mid = (hi + lo) / 2;
  253.  
  254.     while (1) {
  255.         d = strcmp(buf, pm[mid]->function);
  256.         if (d == 0)
  257.             break;
  258.  
  259.         if (lo >= hi) {
  260.             mid = -1;
  261.             break;
  262.         }
  263.         if (d < 0) {
  264.             hi = mid - 1;
  265.         } else {
  266.             lo = mid + 1;
  267.         }
  268.         mid = (hi + lo) / 2;
  269.     }
  270.  
  271.     return (mid);
  272. }
  273.  
  274.  
  275. /* doprint - print the function name and sub - functions */
  276.  
  277. static char lib[] =
  278. {"(library)"};
  279. static char use[] =
  280. {"Used="};
  281. static char fct[] =
  282. {"Functs="};
  283.  
  284. int doprint(int n)
  285. {
  286.     int i, j, k, l, ret;
  287.     struct Mod_list *p;
  288.     struct Func_list *q;
  289.  
  290.     l = n;
  291.     p = pm[l];
  292.  
  293.     /* add function to list for recursion check */
  294.  
  295.     rlist[depth] = p->function;
  296.  
  297.     pagebreak();
  298.  
  299.     setpage(pm[l]);
  300.     ret = page - 1;
  301.     pblock(bfr, p->function, (p->name)->name, fct, p->qty);
  302.  
  303.     depth++;
  304.     strcat(bfr, "   |");
  305.  
  306.     k = p->qty;
  307.     for (j = 0, q = p->ptr; j < k; j++, q++) {
  308.         pagebreak();
  309.         i = find_mod(q->name);
  310.  
  311.         if (recur_chk(q->name)) {
  312.             leftmargin();        /* v1.4 */
  313.             printf("%s\n", bfr);    /* v1.4 */
  314.             if (i >= 0)
  315.                 setpage(pm[i]);
  316.             pblock(bfr, q->name, "(recursive)", "", 0);
  317.             line++;
  318.         } else {
  319.             if (i >= 0) {
  320.                 if (pm[i]->used == 1) {
  321.  
  322.                     /* got a new function */
  323.  
  324.                     leftmargin();        /* v1.4 */
  325.                     printf("%s\n", bfr);    /* v1.4 */
  326.                     line++;
  327.                     doprint(i);        /* used only once */
  328.                 } else {
  329.  
  330.                     /* a previously defined function */
  331.  
  332.                     leftmargin();        /* v1.4 */
  333.                     printf("%s\n", bfr);    /* v1.4 */
  334.                     setpage(pm[i]);
  335.                     pblock(bfr, q->name, "(defined)",
  336.                            use, q->used);
  337.                     line++;
  338.                 }
  339.             } else {
  340.  
  341.                 /* a library function */
  342.  
  343.                 leftmargin();        /* v1.4 */
  344.                 printf("%s\n", bfr);    /* v1.4 */
  345.                 pblock(bfr, q->name, lib, use, q->used);
  346.                 line++;
  347.             }
  348.         }
  349.     }
  350.  
  351.     /* remove the function from the recursion list */
  352.  
  353.     rlist[depth] = NULL;
  354.     bfr[strlen(bfr) - 4] = 0;
  355.     depth--;
  356.     return (ret);
  357. }
  358.  
  359.  
  360. /* getstats - get the number of times each
  361.               function is used */
  362.  
  363. void getstats(void)
  364. {
  365.     register int i;
  366.     int j;
  367.     register struct Func_list *p;
  368.  
  369.     p = Flist;
  370.  
  371.     for (i = 0; i < Fqty; i++) {
  372.         j = find_mod(p->name);        /* see if the name exists */
  373.         if (j >= 0)
  374.             pm[j]->used += p->used;
  375.         p++;
  376.     }
  377. }
  378.  
  379.  
  380. /* pblock - print a function block */
  381.  
  382. static void pblock(char *pre, char *fptr, char *mptr, char *sptr, int cnt)
  383.  
  384. {
  385.     leftmargin();    /* v1.4 */
  386.     printf("%s %s\n", pre, tline);
  387.     leftmargin();
  388.     printf("%s-+%-25s|\n", pre, fptr);
  389.     leftmargin();
  390.     printf("%s |%-12s %8s%3d |\n",
  391.             pre, mptr, sptr, cnt);
  392.     leftmargin();
  393.     printf("%s %s\n", pre, tline);
  394.     line += 4;
  395.  
  396. }
  397.  
  398.  
  399. /* pagebreak - check for a page break and if so
  400.                then print the page header */
  401.  
  402. void pagebreak(void)
  403. {
  404.     int i;
  405.     static char title[] =
  406.     {"C PRINTER  - (c) 1987, 1988  rev. 1.2"};
  407.  
  408.     if (pl == 0 && line == 9999) {
  409.         printf("\n\n\n\n");        /* v1.4 */
  410.         line = 0;
  411.     } else if (pl != 0) {
  412.         if (line > (pl - 11)) {
  413.             printf("%c", 0x0c);        /* v1.4 */
  414.             line = 0;
  415.         }
  416.         if (line == 0) {
  417.             leftmargin();            /* v1.4 */
  418.  
  419.             printf("%s", title);        /* v1.4 */
  420.             for (i = strlen(title); i < width - 10; i++)
  421.                 fputc(' ', stdout);        /* v1.4 */
  422.             printf("Page:%4d\n", page);    /* v1.4 */
  423.  
  424.             leftmargin();                /* v1.4 */
  425.             for (i = 0; i < width; i++)
  426.                 fputc('-', stdout);        /* v1.4 */
  427.             printf("\n\n");                /* v1.4 */
  428.             line = 3;
  429.             page++;
  430.         }
  431.     }
  432. }
  433.  
  434.  
  435. /* recur_chk - check if the function just called
  436.                is one being processed */
  437.  
  438. int recur_chk(char *buf)
  439.  
  440. {
  441.     register char **p;
  442.     int ret;
  443.  
  444.     p = rlist;
  445.  
  446.     while (*p != NULL && strcmp(*p, buf)) {
  447.         p++;
  448.     }
  449.  
  450.     if (*p == NULL)
  451.         ret = 0;                /* the function was not in the list */
  452.     else
  453.         ret = 1;                /* found it */
  454.  
  455.     return ret;
  456. }
  457.  
  458.  
  459. /* setpage - put the current page number
  460.              into the linked page list */
  461.  
  462. static void setpage(struct Mod_list *ptr)
  463.  
  464. {
  465.     struct Pages *p;
  466.  
  467.     p = ptr->pg;
  468.     if (p == NULL) {
  469.         p = (struct Pages *) malloc(sizeof(struct Pages));
  470.         if (p == NULL) {
  471.             fprintf(stderr,
  472.                     "Ran out of memory for page # list.\n");
  473.             exit(1);
  474.         }
  475.         ptr->pg = p;
  476.         p->next = NULL;
  477.         p->pg = page - 1;
  478.     } else {
  479.         while (p->next != NULL)
  480.             p = p->next;
  481.         p->next = (struct Pages *) malloc(sizeof(struct Pages));
  482.         if (p->next == NULL) {
  483.             fprintf(stderr,
  484.                     "Ran out of memory for page # list.\n");
  485.             exit(1);
  486.         }
  487.         p = p->next;
  488.         p->next = NULL;
  489.         p->pg = page - 1;
  490.     }
  491. }
  492.  
  493.  
  494. /* strcheck - check if the character is
  495.  * in the variable name set
  496.  */
  497.  
  498. int strcheck(char c)
  499.  
  500. {
  501.     if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
  502.         c == '_' || (c >= '0' && c <= '9'))
  503.         return (1);
  504.     else
  505.         return (0);
  506. }
  507.  
  508.  
  509. void stop(void)
  510. {
  511.     printf("hello");
  512. }
  513.  
  514.  
  515. /* print the left margin for the printout */
  516.  
  517. void leftmargin(void)    /* v1.4 */
  518. {
  519.     register int i;
  520.  
  521.     for (i = 0; i < lm; i++)
  522.         fputc(' ', stdout);        /* v1.4 */
  523. }
  524.